﻿using System;
using System.Collections.Generic;
using System.Dynamic;

namespace CommonEngine
{
    /// <summary>
    /// 统一输出---实体属性值封装动态类
    /// </summary>
    public class DyObj : DynamicObject
    {
        public string ParName { get; set; }
        public object ParVal { get; set; }

        /// <summary>
        /// 构造
        /// </summary>
        public DyObj(string PName, object PVal)
        {
            if (string.IsNullOrEmpty(PName))
                return;

            this.ParName = PName;
            this.ParVal = PVal;
        }

        #region----override-----

        /// <summary>
        /// varEn("pname")  ---在dynamic作为引用的情况下--总是返回属性名称---
        /// </summary>
        public override bool TryInvoke(InvokeBinder binder, object[] args, out object result)
        {
            if (string.IsNullOrEmpty(this.ParName))
            {
                result = null;
                return true;
            }

            result = this.ParName;
            return true;
            //return dic.TryGetValue(name, out result); //--参考
        }

        /// <summary>
        /// varEn.funName("pname")---在dynamic作为引用的情况下--总是返回属性值---
        /// </summary>
        public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
        {
            if (string.IsNullOrEmpty(this.ParName))
            {
                result = null;
                return true;
            }

            result = this.ParVal;
            return true;
        }

        /// <summary>
        /// 类型 obj = varEn  ----在dynamic作为引用的情况下----可以直接转换为属性对应的数据类型
        /// ---注意这里是将值给出去---接result的是类型---可能会有动态强转过程---输出时都打成object就好
        /// </summary>
        public override bool TryConvert(ConvertBinder binder, out object result)
        {
            var obj = Convert.ChangeType(this.ParVal, binder.Type);
            if (string.IsNullOrEmpty(this.ParName) || this.ParVal == null)
            {
                result = obj;
                return true;
            }

            if (binder.Type == typeof(object))
            {
                result = this.ParVal;
                return true;
            }
            else if (binder.Type == typeof(string))
            {
                result = this.ParVal.ToString();
                return true;
            }
            else if (binder.Type == obj.GetType())
            {
                result = obj;
                return true;
            }

            return base.TryConvert(binder, out result);
        }

        /// <summary>
        /// 索引---varEn[]---在dynamic作为引用的情况下--任何形式的索引都是取属性名称
        /// </summary>
        public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
        {
            if (string.IsNullOrEmpty(this.ParName))
            {
                result = null;
                return true;
            }

            result = this.ParName;
            return true;
        }
        /// <summary>
        /// 索引设置---varEn[0]="ABC"---做类型判断
        /// ---从外面取值进来的重构---
        /// </summary>
        public override bool TrySetIndex(SetIndexBinder binder, object[] indexes, object value)
        {
            if (string.IsNullOrEmpty(this.ParName))
                return true;

            if (value == null)
            {
                this.ParVal = null;
                return true;
            }

            if (value.GetType() == typeof(object))
            {
                this.ParVal = value;
            }
            else if (value.GetType() == typeof(DyObj))
            {
                dynamic dy = value;
                string pn = dy[0];  //--取属性名称--
                if (this.ParName.Equals(pn))
                {
                    this.ParVal = dy.value;  //--取属性值--赋值
                }
            }

            return true;
        }

        /// <summary>
        /// 获取属性名称
        /// </summary>
        public override IEnumerable<string> GetDynamicMemberNames()
        {
            if (string.IsNullOrEmpty(this.ParName))
                return new List<string>();

            List<string> ls = new List<string> { this.ParName };
            return ls;
        }

        /// <summary>
        /// obj = varEn.ppp --在dynamic作为引用的情况下--总是返回属性的“值”
        /// </summary>
        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            if (string.IsNullOrEmpty(this.ParName))
            {
                result = null;
                return true;
            }

            if (this.ParVal == null)
            {
                result = null;
                return true;
            }

            if (binder.ReturnType == typeof(string))
                result = this.ParVal.ToString();
            else
                result = Convert.ChangeType(this.ParVal, binder.ReturnType);

            return true;
        }

        /// <summary>
        /// varEn.ppp = obj --在dynamic作为引用的情况下--做类型判断
        /// ---从外面取值进来的重构---
        /// </summary>
        public override bool TrySetMember(SetMemberBinder binder, object value)
        {
            if (string.IsNullOrEmpty(this.ParName))
                return true;

            if (value == null)
            {
                this.ParVal = null;
                return true;
            }

            if (value.GetType() == typeof(object))
            {
                this.ParVal = value;
            }
            else if (value.GetType() == typeof(DyObj))
            {
                dynamic dy = value;
                string pn = dy[0];  //--取属性名称--
                if (this.ParName.Equals(pn))
                {
                    this.ParVal = dy.value;  //--取属性值--赋值
                }
            }
            else
                this.ParVal = value;

            return true;
        }

        #endregion

        public override string ToString()
        {
            if (this.ParVal != null)
                return this.ParVal.ToString();
            else
                return string.Empty;
        }
    }
}
